#!/usr/bin/env python

import formDailiesData as fdd
from time import time, sleep, strftime
from ConfigParser import RawConfigParser, NoSectionError, ParsingError
from threading import Thread, Lock
from loginDialog import LoginDialog
from settingsDialog import SettingsDialog
from datetime import datetime
from ritzWin import RitzBrowser
from random import shuffle, uniform
import sys

import logging
logger = logging.getLogger('logfile')
hdlr = logging.FileHandler('logfile.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.removeHandler(hdlr)

detailedLogger = logging.getLogger('detLog')
hdlr = logging.FileHandler('detLog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
detailedLogger.addHandler(hdlr) 
detailedLogger.setLevel(logging.DEBUG)
detailedLogger.removeHandler(hdlr)

CONFIG_LOCK = False

def getTimestamp():
  return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


def getSetting(section, setting, raw=False, item=False):
  config = RawConfigParser()
  while True:
    try:
      config.read('settings.cfg')
      if raw == 'raw':
        try:
          return str(config.get(section, setting))
        except:
          return 0
      else:
        try:
          return eval(config.get(section, setting))
        except:
          return str(config.get(section, setting))
    except:
      sleep(.2)

def getUserAgent(username):
  return DEFAULT_USER_AGENT



DEFAULT_USER_AGENT = getSetting('def', 'useragent')
BETWEENDAILIESMIN = getSetting('def', 'betweendailiesmin')
BETWEENDAILIESMAX = getSetting('def', 'betweendailiesmax')
LONGERDELAYMIN =    getSetting('def', 'longerDelayMin')
LONGERDELAYMAX =    getSetting('def', 'longerDelayMax')
PAGEMIN =           getSetting('def', 'pageMin')
PAGEMAX =           getSetting('def', 'pageMax')



def getBetweenDailysTime():
  return uniform( float(BETWEENDAILIESMIN), float(BETWEENDAILIESMAX) )


def getLongerSleepTime():
  return uniform( float(LONGERDELAYMIN), float(LONGERDELAYMAX) )


def getPageSleepTime():
  return uniform( float(PAGEMIN), float(PAGEMAX) )



class AbortException(Exception):

  def __init__(self,*args):
    self.args = args or ['Abort!']



class DailyRunner(Thread):
  def __init__(self, username, lock, testMode = False):
    Thread.__init__(self)
    self.finished = False
    self.lock = lock
    self.br = RitzBrowser(getUserAgent(username), testMode)
    self.testMode = testMode
    self.username = username
    self.dailiesToDo = self.determineDailiesToDo()
    shuffle(self.dailiesToDo)
    self.start_time = time()
    self.start()


  def abort(self):
    print 'ABORTING!'
    self.userLog('ABORTING!!!!')
    raise AbortException()


  def run(self):
    if self.login():
      print '[%s] succesfful login' % self.username
      self.doDailies()
    else:
      print 'login failed'


  def determineDailiesToDo(self):
    allAvailableDailies = getSetting('def','execchoices')
    actualDailiesToDo = []
    for item in allAvailableDailies:
      ts = int(getSetting(self.username, item, 'raw'))
      lastPlayed = datetime.fromtimestamp(ts)
      freq = fdd.dailyData[str(item)]['freq']
      if freq == 'daily':
        sameDay = lastPlayed.strftime('%j') == datetime.fromtimestamp(int(time())).strftime('%j')
        if not sameDay:
          actualDailiesToDo.append(item)
      else:
        minuteDiff = (int(time()) - ts)/60
        if minuteDiff>int(freq):
          actualDailiesToDo.append(item)
    return actualDailiesToDo


  def login(self):
    while True:
      try:
        resp = self.br.doLogin(self.username, getSetting(self.username, 'password'), getSetting(self.username, 'proxy'), 3.7)
        break
      except TypeError:
        print '[%s] trying again' % self.username
        sleep(1)
    if resp == 'Successful login':
      return True
    return False


  def userLog(self, infoToLog, importantLog=False):
    try:
      stuffToLog = '[%s] %s' % (self.username, infoToLog)
    except:
      stuffToLog = '[%s] %s' % (self.username, str(infoToLog))
    if importantLog:
      logger.info(stuffToLog)
    detailedLogger.info(stuffToLog)


  def storeLastVisit(self, player, daily):
    self.lock.acquire()
    config = RawConfigParser()
    try:
      try:
        config.read('settings.cfg')
      except ParsingError:
        print 'parse err'
        sleep(.3)
      if player not in config.sections():
        config.add_section(player)
      config.set(player, daily, int(time()))
      config.set('def','lastloadedplayer',player)
      with open('settings.cfg','wb') as f:
        config.write(f)
      self.lock.release()
    except NoSectionError:
      sleep(.2)
      print 'waitin'



  def doDailies(self):
    def logSleep( sleepSeconds, item ):
      self.userLog( 'Est sleep time for %s: %ss' % (item, str(round(sleepSeconds,2))) )

    def logSleepList( sleepSecondsList, item ):
      totalSleeps = str(round(eval(''.join(["+%s" % wt for wt in sleepSecondsList])),2))
      self.userLog( 'Est total time for %s: %ss' % (item, totalSleeps) )

    print '%s doing %s' % (self.username, str(self.dailiesToDo))
    for item in self.dailiesToDo:
      daily_start_time = time()
      self.userLog('Start %s' % item)

      betweenGets = getBetweenDailysTime()
      waitTime = getPageSleepTime()
      longerWaitTime = getLongerSleepTime()
      self.userLog("Waiting before %s for %s seconds" % (item, betweenGets))
      response = ''
      if not self.testMode:
        sleep( betweenGets )
      if item == 'Tombola': 
        logSleep(waitTime, item)
        response = self.br.getTombola( waitTime )
      elif item == 'Merry Go Round': 
        waitTimes = [getPageSleepTime() for i in range(6)]
        logSleepList(waitTimes, item)
        response = self.br.getMerryGoRound( waitTimes )
      elif item == 'Shrine': 
        logSleep(waitTime, item)
        response = self.br.getShrine( waitTime )
      elif item == 'Check mail': 
        waitTimes = [getPageSleepTime() for i in range(50)]
        logSleepList(waitTimes, item)
        response = self.br.checkMail( waitTimes )
      elif item == 'Food club': 
        waitTimes = [getPageSleepTime() for i in range(13)]
        logSleepList(waitTimes, item)
        response = self.br.getFoodClub( waitTimes ,1,1)
      elif item == 'Altador': 
        waitTimes = [getPageSleepTime() for i in range(3)]
        logSleepList(waitTimes, item)
        response = self.br.getAltador( waitTimes )
      elif item == 'Slug': 
        logSleep(waitTime, item)
        response = self.br.getSlug( waitTime )
      elif item == 'Omelette': 
        logSleep(waitTime, item)
        response = self.br.getOmelette( waitTime )
        if getSetting('def', 'eatomelette'):
          waitTime2 = getPageSleepTime()
          logSleep(waitTime2, item)
          sleep(waitTime2)
          waitTimesList = [getPageSleepTime() for i in range(7)]
          logSleepList(waitTimesList, item)
          try:
            omelette = response.split('.')[0]
            response = self.br.getFeedOmelette(waitTimesList, omelette, self.br.getCurrentPet())
          except:
            response = "Failed to feed pet omelette, probably didn't get omelette"
      elif item == 'Anchor': 
        logSleep(waitTime, item)
        response = self.br.getAnchor( waitTime )
      elif item == 'Bob4Apples': 
        logSleep(waitTime, item)
        response = self.br.getBobApples( waitTime )
      elif item == 'Ice Scratch Card': 
        logSleep(waitTime, item)
        response = self.br.getIceScratchCard( waitTime )
      elif item == 'Desert Scratch Card': 
        logSleep(waitTime, item)
        response = self.br.getDesertScratchCard( waitTime )
      elif item == 'Halloween Scratch Card' : 
        logSleep(waitTime, item)
        response = self.br.getHalloweenScratchCard( waitTime )
      elif item == 'Fruit Machine': 
        logSleep(waitTime, item)
        response = self.br.getFruitMachine( waitTime )
      elif item == 'Plushie Of Prosperity' : 
        logSleep(waitTime, item)
        response = self.br.getPlushieOfProsperity( waitTime )
      elif item == 'Fishing': 
        logSleep(waitTime, item)
        response = self.br.getFishing( waitTime )
      elif item == 'Healing Springs': 
        logSleep(waitTime, item)
        response = self.br.getHealingSprings( waitTime )
      elif item == 'Jelly': 
        logSleep(waitTime, item)
        response = self.br.getJelly( waitTime )
      elif item == 'Wheel of Excitement': 
        logSleep(waitTime, item)
        response = self.br.getWheelOfExcitement( waitTime )
      elif item == 'Snowager': 
        logSleep(waitTime, item)
        response = self.br.getSnowager( waitTime )
      elif item == 'Trivia Question': 
        logSleep(waitTime, item)
        response = self.br.getTriviaQuestion( waitTime )
      elif item == 'Forgotten Shore': 
        logSleep(waitTime, item)
        response = self.br.getForgottenShore( waitTime )
      elif item == 'Wishing Well': 
        waitTimes = [getPageSleepTime() for i in range(10)]
        logSleepList( waitTimes , item)
        response = self.br.getWishingWell( waitTimes, getSetting('def', 'wellamount'), getSetting('def', 'wellwish') )
      elif item == 'Toy Chest': 
        logSleep(waitTime, item)
        response = self.br.getToyChest( waitTime )
      elif item == 'Bank Interest': 
        logSleep(waitTime, item)
        response = self.br.getBankInterest( waitTime )
        if getSetting('def', 'extrabankactions'):
          waitTime2 = getPageSleepTime()
          logSleep( waitTime2 , item)
          self.br.getBankDeposit( waitTime2, getSetting('def', 'depositmultiplier'), getSetting('def', 'depositifover') )
      elif item == 'Sell Stocks': 
        logSleep(longerWaitTime, item)
        response = self.br.sellStocks( longerWaitTime, getSetting('def', 'sellstockmin') )
      elif item == 'Wise King': 
        logSleep(longerWaitTime, item)
        response = self.br.getWiseKing( longerWaitTime )
      elif item == '20x Bagatelle': 
        logSleep(waitTime, item)
        waitTimes = [getPageSleepTime()+2 for i in range(21)]
        logSleepList( waitTimes , item)
        response = self.br.getBagatelle( waitTime, waitTimes )
      elif item == 'Grumpy King': 
        longerWaitTimes = [getLongerSleepTime() for i in range(2)]
        est1 = waitTime
        est2 = sum(longerWaitTimes)
        logSleepList( longerWaitTimes , item)
        response = self.br.getGrumpyKing( waitTime, longerWaitTimes )
      elif item == 'Buy 1000x Stocks':
        max = getSetting('def', 'buystockmax')
        waitTimes = [getPageSleepTime() for i in range(3)]
        logSleepList( waitTimes , item)
        response = self.br.getStocks( waitTimes, max )
      elif item == 'Lunar Temple': 
        waitTimes = [getPageSleepTime() for i in range(4)]
        logSleepList( waitTimes , item)
        response = self.br.getLunarTemple( waitTimes )
      elif item == 'Meteor': 
        waitTimes = [getPageSleepTime() for i in range(9)]
        logSleepList( waitTimes , item)
        response = self.br.getMeteor( waitTimes )
      elif item == 'Potato Counter': 
        logSleep(longerWaitTime, item)
        waitTimes = [getLongerSleepTime() for i in range(3)]
        betweenCountsWait = [getPageSleepTime() for i in range(3)]
        est1 = sum(waitTimes)
        est2 = sum(betweenCountsWait)
        logSleepList( waitTimes , item)
        response = self.br.getPotatoCounter( betweenCountsWait, waitTimes )
      resultDict = {item:{'reward':response,
                                                        'np':self.br.getNP(), 
                                                        'currentPet':self.br.getCurrentPet(), 
                                                        'shopSpace':self.br.getShopSpace(), 
                                                        'hunger' : self.br.getPetHunger(), 
                                                        'mood' : self.br.getPetMood(), 
                                                        'bankTotal' : self.br.getBankTotal()}}
      self.userLog('%s -> %s' % (item, response))
      self.storeLastVisit(self.username, item)
      totalTime = str(int(time()) - int(daily_start_time))
      self.userLog('End %s, total time: %ss' % (item, totalTime))

    if getSetting('def', 'itemsIntoShopAfter'):
      betweenGets = getBetweenDailysTime()
      logSleep( betweenGets , 'Items into shop')
      if not self.testMode:
        sleep( betweenGets )
      waitTime = getPageSleepTime()
      logSleep( waitTime , 'Items into shop')
      response = self.br.getItemsIntoShop( waitTime )
      self.userLog('%s -> %s' % ('Items into shop', response))

    if getSetting('def', 'auctionItemsFromFile'):
      betweenGets = getBetweenDailysTime()
      logSleep( betweenGets , 'Auctioning items from file')
      if not self.testMode:
        sleep( betweenGets )
      waitTimes = [getPageSleepTime() for i in range(30)]
      logSleepList( waitTimes , 'Auctioning items est')
      response = self.br.getAuctionFromFile( waitTimes )
      self.userLog('%s -> %s' % ('Auctioned items', response))

    if getSetting('def', 'itemsIntoShopAfter') and getSetting('def', 'auctionItemsFromFile'):
      betweenGets = getBetweenDailysTime()
      logSleep( betweenGets , 'Items into shop')
      if not self.testMode:
        sleep( betweenGets )
      waitTime = getPageSleepTime()
      response = self.br.getItemsIntoShop( waitTime )
      logSleep( betweenGets , 'Items into shop')
      self.userLog('%s -> %s' % ('Items into shop', response))

    self.userLog(self.getRunInfo(), True)
    self.finished = True


  def getRunInfo(self):
    player = self.username
    bankTotal = self.br.getBankTotal()
    shopSpace = self.br.getShopSpace()
    pet = self.br.getCurrentPet()
    petHunger = self.br.getPetHunger()
    currentNP = self.br.getNP()
    end_time = time()
    total_time = (int(end_time) - int(self.start_time))/60
    return "%s: NP: %s+%s, \nShop Space: %s, %s hunger: %s \nRun time: %smins" % (player, bankTotal, currentNP, shopSpace, pet, petHunger, str(total_time))




class Spawner:
  def __init__(self, lock, testMode ):
    self.runners = {}
    self.testMode = testMode
    self.lock = lock
#    self.spawnDR('williamsdayna24871')
#    sleep(.1)
#    self.spawnDR('rainbowracer222')
#    sleep(.2)
#    self.spawnDR('cinderella_kittens')
    self.schedDict = {}
    self.initializeSchedule()
    try:
      self.runLoop()
    except KeyboardInterrupt:
      for runner in self.runners:
        self.runners[runner].abort()
      print 'exit'


  def runLoop(self):
    prev_now = False
    while True:
      now = strftime('%H:%M')
      if prev_now != now:
        print now
      prev_now = now
      sys.stdout.write(".")
      sys.stdout.flush()
      sleep(3)
      for runner in self.runners:
        if self.runners[runner].finished:
          del self.runners[runner]
          break
      for user in self.schedDict:
        if self.schedDict[user] == now and user not in self.runners:
          print 'spawned user %s' % user
          self.spawnDR(user)
          sleep(5)


  def initializeSchedule(self):
    config = RawConfigParser()
    config.read('settings.cfg')
    for user in config.sections():
      if user != 'def':
        self.schedDict[user] = getSetting(user, 'schedule')


  def spawnDR(self, username):
    self.runners[username] = DailyRunner(username, self.lock, self.testMode)



if __name__ == '__main__':
  testMode = True
  if len(sys.argv) > 1 and sys.argv[1] == 'p':
    testMode = False
  if testMode:
    print 'Mode: test'
  else:
    print 'Mode: prod'
  lock = Lock()
  s = Spawner(lock, testMode)


